package tools;

import com.alee.laf.optionpane.WebOptionPane;
import configs.ServerConfig;
import constants.ServerConstants;
import handling.netty.MapleCustomEncryption;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import server.MapleStatEffectFactory;
import server.ShutdownServer;
import server.Timer;
import server.console.Start;
import tools.packet.BuffPacket;

import java.io.*;
import java.net.Socket;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;

/**
 * @author CHMS
 *         创建日期 2016/6/4
 */
public class Authorization {

    private static final Logger log = LogManager.getLogger();
    public static String AUTH_LIMIT_TIME = "1970-01-01";
    public static int AUTH_LIMIT_DAY = 0;
    private static int failcount = 0;
    private static boolean isPlanShutdown = false;
    private static boolean showException = false;

    /**
     * @param message
     * @return
     */
    public static AuthStatus sendGateMessage(String message) {
        AuthStatus ret;
        String host = ServerConfig.WORLD_TAIWAN ? "auth.maplefun.tw" : "114.215.69.243";//114.215.69.243
        int port = 10288;
        String recv = "";
        try {
            //与服务端建立连接
            Socket client = new Socket(host, port);
            //建立连接后就可以往服务端写数据了
            Writer writer = new OutputStreamWriter(client.getOutputStream());
            writer.write(message + "|" + ServerConfig.LOGIN_MAPLE_VERSION);
            writer.flush();
            //写完以后进行读操作
            BufferedInputStream br = new BufferedInputStream(new DataInputStream(client.getInputStream()));
            int len;
            byte[] buffer = new byte[128];
            while ((len = br.read(buffer)) != -1) {
                byte[] decoder = new byte[len];
                System.arraycopy(buffer, 0, decoder, 0, len);
                MapleCustomEncryption.decryptData(decoder);
                recv = new String(decoder, "GBK");
            }
            writer.close();
            br.close();
            client.close();
        } catch (Exception e) {
            log.error("与授权服务器连接失败，请查看服务器是否能打开百度网页，若无法打开请联系机房解决网络问题。", e);
        }
        if (MapleStatEffectFactory.logname.isEmpty()) {
            BuffPacket.writeForeginBuff(null);
        }
        RecvAuthData rad = new RecvAuthData(recv);
        if (rad.isMulit()) {
            if (!rad.getKey().equals(message)) {
                ret = AuthStatus.AUTH_FAIL;
            } else if (!rad.getCurrTime().equals(getBJTime())) {
                ret = AuthStatus.AUTH_TIMEOUT;
            } else {
                ServerConstants.SERVER_FLAG = rad.getFlag();
                AUTH_LIMIT_DAY = rad.getLimitday() + 1;
                if (AUTH_LIMIT_DAY < 4) {
                    if (AUTH_LIMIT_DAY == 1 && !isPlanShutdown) {
                        isPlanShutdown = true;
                        Timer.GuiTimer.getInstance().schedule(() -> {
                            ShutdownServer.getInstance().shutdown();
                            System.exit(0);
                        }, DateUtil.getNextDayDiff(1));
                    }
                    if (!showException) {
                        showException = true;
                        int confirmDialog = WebOptionPane.showConfirmDialog(null, "当前服务器还有 " + AUTH_LIMIT_DAY + "天过期，请及时续费 QQ：503355336", "", WebOptionPane.YES_NO_OPTION);
                        if (confirmDialog == WebOptionPane.YES_OPTION || confirmDialog == WebOptionPane.NO_OPTION) {
                            showException = false;
                        }
                    }
                }
                ret = AuthStatus.AUTH_SUCCESS;
            }
        } else {
            switch (recv) {
                case "Authorization has expired.":
                    ret = AuthStatus.AUTH_TIMEOUT;
                    break;
                case "Unauthorized Server.":
                    ret = AuthStatus.AUTH_UNKNOWN;
                    break;
                default:
                    ret = AuthStatus.AUTH_FAIL;
                    break;
            }
        }

        if (rad.isMulit()) {
            Date temp_date = null;
            String safedate = String.valueOf(rad.getAuthTime().substring(0, 10));
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            try {
                Date d = format.parse(safedate);
                Calendar c = Calendar.getInstance();
                c.setTime(d);
//                c.add(Calendar.DATE, rad.getLimitday());
                temp_date = c.getTime();
            } catch (ParseException e) {
                System.err.println("系统错误!");
            }
//            if (WinStart.getInstance() == null) {
//                Console.setTitle("冒险岛服务端控制平台 【彩虹工作室出品 QQ：503355336】 过期时间：" + format.format(temp_date));
//            } else {
//                WinStart.getInstance().setTitle("冒险岛服务端控制平台 【彩虹工作室出品 QQ：503355336】 过期时间：" + format.format(temp_date));
//            }
            AUTH_LIMIT_TIME = format.format(temp_date);
        }

        return ret;
    }

    public static String getBJTime() {
        String bjTime = null;
        String weburls[] = ServerConfig.WORLD_TAIWAN ? new String[]{"http://www.google.com"} : new String[]{"http://open.baidu.com/", "http://www.qq.com", "http://www.163.com", "http://www.google.com"};
        for (String weburl : weburls) {
            try {
                //这是通过网络获取北京时间的方法
                java.util.Locale locale = java.util.Locale.CHINA; //这是获得本地中国时区
                String pattern = "yyyy-MM-dd-HH";//这是日期格式
                java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(pattern, locale);//设定日期格式
                java.util.Date date;
                java.net.URL url = new URL(weburl);//取得资源对象
                java.net.URLConnection uc = url.openConnection();//生成连接对象
                uc.setConnectTimeout(10000);
                uc.setReadTimeout(10000);
                uc.connect(); //发出连接
                long ld = uc.getDate(); //取得网站日期时间
                if (ld == 0) {
                    continue;
                }
                date = new Date(ld); //转换为标准时间对象
                bjTime = df.format(date);
                break;
            } catch (IOException ex) {
                log.error("同步时间失败", ex);
                System.err.println("同步时间失败,请检查网络是否通畅,是否能打开 www.qq.com 与 www.163.com");
            }
        }
        return bjTime;
    }

    public static void AutoCheckAuth() {
        Timer.GuiTimer.getInstance().register(() -> {
            AuthStatus ret = checkAuth().getLeft();
            if (ret != AuthStatus.AUTH_SUCCESS) {
                if (failcount >= 3) {
                    ShutdownServer.getInstance().shutdown();
                    System.exit(0);
                }
                failcount++;
            } else {
                failcount = 0;
            }
        }, 60 * 60 * 1000, 60 * 60 * 1000);
    }

    public static Pair<AuthStatus, String> checkAuth() {
        //获取当前机器的key
        String key = IPAddressTool.getkey();
        if (NoCheckKey.contains(key)) {
            return new Pair<>(AuthStatus.AUTH_NOCHECK, key);
        }
    /*    Pair<AuthStatus, String> ret = new Pair<>(sendGateMessage(key), key);
        switch (ret.getLeft()) {
            case AUTH_TIMEOUT:
                System.setProperty("wzpath", "../wz" + String.valueOf(Randomizer.nextInt(1029480184)));
                System.out.println("授权已到期，请联系客服QQ：503355336");
                if (Start.startFinish) {
                    ShutdownServer.getInstance().shutdown();
                }
                break;
        }
        return ret;*/
        System.out.println("key = " + key);
        System.setProperty("wzpath", "../wz" + String.valueOf(Randomizer.nextInt(1029480184)));
        System.out.println("未授权，请联系QQ：467444339");
        return new Pair<>(AuthStatus.AUTH_TIMEOUT, key);
    }

    public enum NoCheckKey {
        SHASHA("3F60F928865007AF1B2803B685E0E5B5"),
        SHASHAMAC("63BB9F88C632D977D03E9CEE93902DA2"),
        SHASHAMAC2("E2F3C444DBFA87B3BF1E67E4B21DED39"),
        SHASHA_WLAN("CECF5F0C6DE3BF1170EAEABE6963A2B5"),
        童心冒险岛("86E4FE279137F9CF5D629BB991AA2605"),
        芒果冒险岛("80A8C81A587E2494B208F0AE8572F757"),
        木叶冒险岛("7FB50F05C1942A607C271C2565C13710"),
        新世界冒险岛("3CCA1F828ED8FEE8BB00AB1663E5C48A"),
        天天向上岛("94936A5BFB7D0B183A64A2E4F984E2B7"),
        梦梦冒险岛("E7EEAE1FF9BD8A66F7A384B0E527911F"),
        养老院("89E56FA10E276998182DECB05FC02D02"),
        星光冒险岛("312116C29B72FA8CEEB56C30DF39AF76"),
        无限冒险岛("2B356A3AD3D4832FA4752479F21CF299"),
        完美冒险岛("B223EB7DCCD2E855CECA5FB59AB84325"),
        小清新冒险岛("D1E885C26E42B770D03B9BF0D96ACA1D"),
        未来冒险岛("8700CDCFE171F8D89C57BD20B22B1C0C"),
        归来冒险岛("4B7D0660B5552E89BDFAE0A3EFA9746B"),
        枫树冒险岛("B5190E3B4FFBB02D91F6D969E04F846A"),
        新叶城冒险岛("283361AC89947C807AE79CB34D012DB0"),
        米虫冒险岛("4DA4C00BEC260415B67748CEC81F695E"),
        菠萝冒险岛("FC34C795E83C1BB1FF6ED2760CC6435E"),
        匠心冒险岛("2C366EE24A11AD51B70147287E6E4F09"),
        征服冒险岛("97E2F2899079C1AFFA988F033D300DAC"),
        Angel丶国度("DA66812CC81AD4C1EE539DAB9D779D6F"),
        嘉年华冒险岛("283361AC89947C807AE79CB34D012DB0"),
        脱胎换谷("2F238D7A347CA955437EAADA6ACA0E7C"),
        奥叮冒险岛("CE8903173BE0F6F935E207192906916C"),
        摩登冒险岛("995865AF9BE858A92A1729249F3B6E20"),
        几里测试服("A0498D51AB142C2E6378322381F82855"),
        蜗牛冒险岛("D78171AD40EFEEEA2A21F1A78AB11BBB"),
        ;

        String key;
        public static boolean isDevelop = false;

        NoCheckKey(String key) {
            this.key = key;
        }

        public static boolean contains(String key) {
            return Arrays.stream(NoCheckKey.values()).anyMatch(it -> it.key.equals(key));
        }

        public static void checkDevelop(String key) {
            isDevelop = key.equals(SHASHA.key) || key.equals(SHASHA_WLAN.key) || key.equals(SHASHAMAC.key) || key.equals(SHASHAMAC2.key);
        }
    }

    public enum AuthStatus {

        AUTH_SUCCESS,
        AUTH_TIMEOUT,
        AUTH_UNKNOWN,
        AUTH_FAIL,
        AUTH_NOCHECK
    }

    static class RecvAuthData {
        public long flag;
        private String key, currTime, authTime;
        private int limitday;
        private boolean mulit;

        RecvAuthData(String recv) {
            String[] recvs = recv.split("\\|");
            mulit = recvs.length > 1;
            if (mulit) {
                key = recvs[0];
                currTime = recvs[1];
                authTime = recvs[2];
                flag = Long.parseLong(recvs[3]);
                limitday = Integer.parseInt(recvs[4].trim());
            }
        }

        public String getKey() {
            return key;
        }

        public String getCurrTime() {
            return currTime;
        }

        public String getAuthTime() {
            return authTime;
        }

        public long getFlag() {
            return flag;
        }

        public int getLimitday() {
            return limitday;
        }

        public boolean isMulit() {
            return mulit;
        }
    }
}
